home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
scope
/
001-025
/
scopedisk3
/
virusx121
/
virusx.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-18
|
17KB
|
583 lines
/* VirusX - by Steve Tibbett
The complete Virus Elimination System!
Please - if you find a new virus, Send me a copy!
(And warn me it's on the disk!). I want to keep
this program current. (Feel free to put something
neat (but not copyrighted) on the disk also!)
*/
/* History:
A few weeks ago: V1.0 written.
A few days later: V1.01 released - V1.0 wrote garbage when disk was Write Prot.
27-Mar-88: V1.2 - Added Byte Bandit RAM detection, and disk detection.
(Actually, it's well after Midnight - make that 28-Mar-88)
Just after
uploading V1.2
to Amic BBS: Realized I put the wrong version in the ARC file - Had to
rename V1.2 to V1.21...
*/
/* - Ok, it's not the cleanest code in the world - it was written in two
days, for a specific purpose, and it works! */
struct Port *diskport; /* disk's port.*/
struct IOStdReq *diskreq; /* disk's IOStdReq */
int DisksChecked, DisksInstalled, SCAFound; /* for title bar info */
char titlebuffer[80];
/* Who needs includes with Aztec? Everything's precompiled! */
#include <devices/bootblock.h>
/* Ok, ONE include... */
/* Amount of boot code we've got (approx): */
#define BSIZE 40
int ChangeCount[4]; /* TD_CHANGECOUNT for all 4 drives */
int LastSum; /* Used in the checksumming */
int CheckDrives; /* Boolean, from the command line */
int error; /* sort of a temporary variable sort of */
unsigned char diskbuffer[3*512];/* Everything ends up in here.
I suppose I should have AllocMem'ed this,
but it's SO easy this way */
/* Warning messages. These messages get modified before being displayed
(Unless you DO have a DF9:) */
char TEXTPTR[] = "Danger: The disk in DF9: is";
char NBCTEXT[] = "Danger: The disk in DF9: has"; /* What a waste, eh? */
char CopyText[40];
/* This is a byte by byte copy of working boot block code. Check it
out if you like. This is what gets written back to the disk when you
ask VirusX to fix a disk. */
unsigned char bootblock[] = { 'D', 'O', 'S', 0, 0xc0, 0x20, 0x0f, 0x19,
0, 0, 3, 0x70, 0x43, 0xfa, 0, 0x18,
0x4e, 0xae, 0xff, 0xa0, 0x4a, 0x80, 0x67, 0x0a, 0x20, 0x40, 0x20, 0x68,
0x00, 0x16, 0x70, 0x00, 0x4e, 0x75, 0x70, 0xff, 0x60, 0xfa, 0x64,
0x6f, 0x73, 0x2e, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x79,0,0,0,0,0};
/* for IntuiText's */
char def_font[] ="topaz.font";
struct TextAttr TxtAt_Plain = { (UBYTE *)def_font, 8,
FS_NORMAL, FPF_ROMFONT};
/*** Non SCA warning requester IntuiText's ***/
struct IntuiText Body2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *)"Nonstandard Boot Code!", NULL };
struct IntuiText Body1 = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)NBCTEXT, &Body2 };
struct IntuiText Pos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL };
struct IntuiText Neg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL };
/***** SCA Danger Requester IntuiText's ******/
struct IntuiText SCABody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with an SCA Virus!!", NULL };
struct IntuiText SCABody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)TEXTPTR, &SCABody2 };
struct IntuiText SCAPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Remove it", NULL };
struct IntuiText SCANeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Ignore it", NULL };
/***** BBANDIT Requester IntuiText's ******/
struct IntuiText BBDiskbody3 = {
0, 1, JAM2, 20,30, &TxtAt_Plain, CopyText, NULL };
struct IntuiText BBDiskbody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "infected with the Byte Bandit VIRUS!", &BBDiskbody3};
struct IntuiText BBDiskbody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)TEXTPTR, &BBDiskbody2 };
/***** BBandit Notice - Removed from Memory ****/
struct IntuiText BBMem3 = {
0, 1, JAM2, 20,8, &TxtAt_Plain,(UBYTE *) "NOTICE: The Byte Bandit VIRUS was found", NULL };
struct IntuiText BBMem2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "in memory, and is now disabled. See the", &BBMem3 };
struct IntuiText BBMem1 = {
0, 1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "documentation for more information!", &BBMem2 };
struct IntuiText BBMPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, " Thanks! ", NULL };
struct IntuiText BBMNeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, " Thanks! ", NULL };
/***** Write Protect Error Requester IntuiText's ******/
struct IntuiText ERRBody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "Write Protected.", NULL };
struct IntuiText ERRBody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"DISK ERROR: Disk is", &ERRBody2 };
struct IntuiText ERRPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Retry", NULL };
struct IntuiText ERRNeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Cancel", NULL };
/***** Rewrite block? Really? ******/
struct IntuiText REWBody3 = {
0, 1, JAM2, 20,28, &TxtAt_Plain,(UBYTE *) "boot sectors?", NULL };
struct IntuiText REWBody2 = {
0, 1, JAM2, 20,18, &TxtAt_Plain,(UBYTE *) "rewrite that disk's boot", &REWBody3};
struct IntuiText REWBody = {
0, 1, JAM2, 20, 8, &TxtAt_Plain, (UBYTE *)"Are you sure you want to", &REWBody2 };
struct IntuiText REWPos = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "Yes", NULL };
struct IntuiText REWNeg = {
0, 1, JAM2, 7,3, &TxtAt_Plain, "No!", NULL };
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Window *LittleWindow;
struct IntuiMessage *Message;
struct RastPort *RP;
int Keepgoing; /* a boolean flag. it's false when we want out. */
int x, y, i; /* left over from my using Basic */
/*** The Newwindow Structure. ***/
char TITLETEXT[] = "VirusX 1.21 by Steve Tibbett";
struct NewWindow NewLittleWindow = {
128, /* Left, Top, Width, Height */
0,
309,
10,
0, /* Frontpen, Backpen */
1,
DISKINSERTED | CLOSEWINDOW | VANILLAKEY | MOUSEBUTTONS, /* IDCMP Flagz */
WINDOWDRAG | WINDOWDEPTH | RMBTRAP | WINDOWCLOSE | NOCAREREFRESH, /* Windo Flagz */
NULL,
NULL,
TITLETEXT, /* My name. Dont touch it!! */
NULL,
NULL,
0,
0,
0,
0,
WBENCHSCREEN,
};
/*********************Da Beginnin*************************/
main(argc, argv)
int argc;
char *argv[];
{
int OldPri;
/* Come on, folks, is intuition never NOT going to be available???? */
IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0);
/* Same with GfxBase. If GfxBase is gone, we DESERVE to crash. */
GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",0);
/* If checkdrives is true, later on it means we want to check all the drives
with disks in them for viruses. */
CheckDrives = TRUE;
/* Save OldPri so we can restore it later on. We're so nice. */
OldPri = SetTaskPri(FindTask(0), 19); /* and stick us up high. */
diskport = CreatePort(0,0);
diskreq = CreateStdIO(diskport);
SetUp();
CheckMemoryForViruses(); /* New to 1.2 - Check is Byte Bandit in RAM? */
DoLittle(); /* The main loop. Do Little. Ya. */
/* restore priorities to saneness, and take off, eh? */
SetTaskPri(FindTask(0), OldPri);
DeletePort(diskport);
DeleteStdIO(diskreq);
exit(FALSE);
}
/*********************/
DoLittle()
{
register int Code;
register int Class; /* gee */
register int KG2; /* KeepGoing 2. Another booleean. */
LittleWindow = OpenWindow(&NewLittleWindow);
if (LittleWindow == NULL) exit(400L); /* No memory to open little window! */
KG2 = TRUE;
RP = LittleWindow->RPort; /* easier than typing Move(LittleWindow->RP... all
the time */
if (CheckDrives == TRUE) /* Check all drives upon execution (fool */
{ /* ChangeCount to 1000) */
for (x = 0; x < 4; x++) ChangeCount[x] = 1000;
CheckBlock(); /* CheckBlock() checks boot block for virus. */
CheckDrives = FALSE; /* so we don't do it again */
};
SetAPen(RP, 1);
SetBPen(RP, 0);
SetDrMd(RP, JAM2); /* ya. JAM 2! Love that name! */
while (KG2 == TRUE)
{
sprintf(titlebuffer, "VirusX: Disks Checked: %d Disks Installed: %d Viruses Found: %d", DisksChecked, DisksInstalled, SCAFound);
SetWindowTitles(LittleWindow, -1, titlebuffer);
Message = GetMsg(LittleWindow->UserPort);
while (Message == NULL)
{
/* Lets be nice to other tasks! Ya! */
Wait(1<<LittleWindow->UserPort->mp_SigBit);
Message = GetMsg(LittleWindow->UserPort);
};
Class = Message->Class;
Code = Message->Code;
if (Message != NULL) ReplyMsg(Message);
if (Class == CLOSEWINDOW)
{
CloseWindow(LittleWindow);
exit(FALSE);
};
if (Class == DISKINSERTED) CheckBlock();
};
/* KG2 = false, we fell thru to here. Ow. */
CloseWindow(LittleWindow);
return;
}
/**********************/
puts(str) /* outputs a string, but is REAL small. */
char *str[];
{
Write(Output(), str, strlen(str));
}
/********************/
/* Opens trackdisk, finds out who's out there, and sets Changecount up accordioningly. */
/********************/
SetUp()
{
for (x = 0; x < 4; x++) /* go thru all 4 possible drives */
{
ChangeCount[x] = 0;
error = OpenDevice("trackdisk.device",x,diskreq,0);
if (error > 0) continue; /* no drive here */
diskreq->io_Command = TD_CHANGENUM;
error = DoIO(diskreq);
ChangeCount[x] = diskreq->io_Actual; /* save changecount for later */
CloseDevice(diskreq);
};
}
/********************************/
/* This routine returns which drive changed disks lately */
/********************************/
WhoChanged()
{
int RetVal; /* The value we'll return */
RetVal = -1; /* return -1 if all else fails */
for (x = 0; x < 4; x++)
{
if (ChangeCount[x] == 0) continue; /* no drive here */
error = OpenDevice("trackdisk.device",x,diskreq,0);
if (error > 0) continue; /* no drive here */
diskreq->io_Command = TD_CHANGESTATE;
DoIO(diskreq);
if (diskreq->io_Actual != 0)
{
continue;
};
diskreq->io_Command = TD_CHANGENUM;
DoIO(diskreq);
if (diskreq->io_Actual != ChangeCount[x])
{
RetVal = x;
ChangeCount[x] = diskreq->io_Actual;
CloseDevice(diskreq);
goto Out;
};
CloseDevice(diskreq);
};
Out:;
return(RetVal);
}
/********************************/
CheckBlock()
{
int Sum, Bootable, Virus; /* Virus is a flag, Bootable is a flag, Sum the cksum. */
int BBandit; /* BBandit is a flag too. Oh well. */
int a, Unit;
int SCA; /* don't get scared, it's just a flag. */
while ((Unit = WhoChanged()) != -1)
{
DisksChecked++;
SCA = FALSE;
BBandit = FALSE;
/* Unit # to open is returned by "WhoChanged()" up above. */
if (Unit == -1) return;
error = OpenDevice("trackdisk.device",Unit,diskreq,0);
if (error > 0) return;
/* I've heard stories that pulling a read request to block zero with a
length of 1024 will cause the virus to write itself back. Not taking
any chances. */
diskreq->io_Command = CMD_READ;
diskreq->io_Data = diskbuffer;
diskreq->io_Length = 3*512;
diskreq->io_Offset = 0;
DoIO(diskreq);
diskreq->io_Length = 0;
diskreq->io_Command = TD_MOTOR;
DoIO(diskreq); /* turn off motor */
if (diskreq->io_Error > 19) return; /* disk error, lemme out */
CloseDevice(diskreq);
Sum = 0;
for (a=0; a<1024; a=a+4)
{
LastSum = Sum;
Sum = Sum + diskbuffer[a+3];
Sum = Sum + (diskbuffer[a+2] * 256);
Sum = Sum + (diskbuffer[a+1] * 65536);
Sum = Sum + (diskbuffer[a] * (65536 * 256));
if (LastSum > Sum) Sum++; /* took me a while to figger this out */
}
if (Sum != 0) return; /* if it's not bootable, we DONT want it! */
if (diskbuffer[0x2b] == '9')
if (diskbuffer[0x2c] == '.')
if (diskbuffer[0x2d] == '8')
if (diskbuffer[0x2e] == '7')
{
SCAFound++;
BBandit = TRUE; /* 9.87 is part of BBandit Virus */
};
/* check specifically for SCA virus */
if (diskbuffer[8] == 'C')
if (diskbuffer[9] == 'H')
if (diskbuffer[10] == 'W')
{
SCA = TRUE; /* CHW is part of SCA virus */
SCAFound++;
};
/* compare boot block with real boot block. If it's not, notify God. */
Virus = FALSE;
for (x = 0; x < 39; x++) /* nuum of lements in bootblock */
{
if (diskbuffer[8+x] != bootblock[8+x])
{
Virus = TRUE;
};
};
/* Oh no, a Virus! */
if (Virus == TRUE)
{
NBCTEXT[23] = '0'+Unit; /* change DF9: to real drive in text */
TEXTPTR[23] = '0'+Unit;
if (SCA == TRUE)
{
/* OH NOOOOO, an SCA virus. Wimpo virus, compared to BBandit */
Delay(1);
error = AutoRequest(LittleWindow, &SCABody, &SCAPos, &SCANeg, 0, 0, 320, 70);
if (error == TRUE) DoInstall(Unit); /* user wants it fixed. */
Delay(1);
}
else if (BBandit == TRUE)
{
/* The Byte Bandit Virus. Tricky bugger, he WAS. */
Delay(1);
sprintf(CopyText, "(Copy Count on this disk: %d)", (diskbuffer[74]*256)+diskbuffer[75]);
error = AutoRequest(LittleWindow, &BBDiskbody, &SCAPos, &SCANeg, 0, 0, 380, 80);
if (error == TRUE) DoInstall(Unit); /* User crying for aid */
Delay(1);
}
else
{
/* Probably just a custom boot block (or a new virus...) */
Delay(1);
error = AutoRequest(LittleWindow, &Body1, &Pos, &Neg, 0, 0, 320, 70);
if (error == TRUE) DoInstall(Unit); /* user wants it neutered. */
Delay(1);
}
};
}; /* End of While Whochanged */
}
/********************************/
/* This is where the boot code gets changed */
/********************************/
DoInstall(un)
int un; /* unit to write to */
{
register int x;
register int Sum;
int err, a;
/* Rewrite disk? Really? */
error = AutoRequest(LittleWindow, &REWBody, &REWPos, &REWNeg, 0, 0, 320, 75);
if (error != TRUE) return; /* user changed his brain. */
DisksInstalled++;
error = OpenDevice("trackdisk.device", un,diskreq,0);
if (error > 0) return;
trygain:
diskreq->io_Command = TD_PROTSTATUS;
DoIO(diskreq); /* check if disk is write protected */
if (diskreq->io_Actual != 0)
{
error = AutoRequest(LittleWindow, &ERRBody, &ERRPos, &ERRNeg, 0, 0, 280, 75);
if (error == TRUE) /* error is true or false, depending on user */
{
goto trygain;
};
CloseDevice(diskreq);
return; /* unrecoverable write protect error!!!!!!!!! */
};
diskreq->io_Command = CMD_READ;
diskreq->io_Data = diskbuffer; /* Move the drive head, make some noise so */
diskreq->io_Length = 512; /* folks know we're doing something. */
diskreq->io_Offset = 44*512;
DoIO(diskreq);
for (x = 0; x < 1024; x++)
diskbuffer[x] = 0; /* clear diskbuffer to zero. clean. */
for (x = 0; x < 50; x++)
{
diskbuffer[x] = bootblock[x]; /* copy boot code into buffer */
};
/* Write it ! */
diskreq->io_Length = 1024; /* here we go! */
diskreq->io_Data = &diskbuffer[0];
diskreq->io_Command = CMD_WRITE;
diskreq->io_Offset = 0L;
DoIO(diskreq);
diskreq->io_Command = CMD_UPDATE; /* flush buffer to disk */
DoIO(diskreq);
error = diskreq->io_Error;
Delay(5);
diskreq->io_Length = 0;
diskreq->io_Command = ETD_MOTOR;
DoIO(diskreq); /* turn off motor */
CloseDevice(diskreq);
if (error > 19)
{
SetWindowTitles(LittleWindow, "Error, Nothing Done.", -1);
}
else
{
SetWindowTitles(LittleWindow, "Disk Healed.", -1);
};
Delay(100);
SetWindowTitles(LittleWindow, TITLETEXT, -1);
}
/************************/
CheckMemoryForViruses()
{
int VirusBase; /* ick, whatta name! */
int Temp;
struct ExecBase *ExecBase;
int *LongMemPointer; /* Used for reading FROM memory */
ExecBase = OpenLibrary("exec.library", 0);
LongMemPointer = FindName(&ExecBase->DeviceList, "trackdisk.device");
Temp = LongMemPointer;
Temp = Temp - 0x1c;
LongMemPointer = Temp; /* Can't do LongMemPointer - 0x1c because then it's
a pointer operation and we get a wrong value */
VirusBase = (*LongMemPointer) - 0x1b8;
LongMemPointer = VirusBase;
if (*LongMemPointer == ('D'<<24) + ('O'<<16) + ('S'<<8)) /* klugo */
{
/* Ok, so we don't really remove it from memory, but we DO render
it harmless. */
PatchMem(VirusBase+0xaa, 0x4e71);
PatchMem(VirusBase+0xac, 0x4e71);
PatchMem(VirusBase+0xae, 0x4e71);
PatchMem(VirusBase+0xb0, 0x4e71); /* NOP's */
PatchMem(VirusBase+0x1c2, 0x6000); /* Change Bxx to BRA */
PatchMem(VirusBase+0x2d2, 0x6000); /* Disable TD and VTI code */
PatchMem(VirusBase+0x388, 0x4e75); /* Make sure it doesn't come back */
PatchMem(VirusBase+0x3ea, 0x0000); /* Kill resident matchword */
PatchMem(VirusBase, 0x0000); /* so WE don't find it again */
error = AutoRequest(LittleWindow, &BBMem1, &BBMPos, &BBMNeg, 0, 0, 395, 78);
};
CloseLibrary(ExecBase);
}
/***********************/
/**********************/
PatchMem(loc, val)
short *loc;
int val;
{
*loc = val;
}